/*  ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 
*   Copyright 2014 Jan-Marwin Wollschläger                                   *
*                                                                            *
*   Licensed under the Apache License, Version 2.0 (the "License");          *
*   you may not use this file except in compliance with the License.         *
*   You may obtain a copy of the License at                                  *
*                                                                            *
*       http://www.apache.org/licenses/LICENSE-2.0                           *
*                                                                            *
*   Unless required by applicable law or agreed to in writing, software      *
*   distributed under the License is distributed on an "AS IS" BASIS,        *
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
*   See the License for the specific language governing permissions and      *
*   limitations under the License.                                           *
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **   */   

import java.util.ArrayList;

/**
 * The default model as it is needed to implement the Model-View-Controller pattern.
 *
 * @author Jan-Marwin Wollschläger
 * @version 0.1
 **/
class DefaultModel implements IModel
{
  private ArrayList<IMolecule> molecules;
  
  public DefaultModel()
  {
    molecules = new ArrayList<IMolecule>();
  }
  
 /**
 * @return Returns the current data of this model, which at this point only 
 * consists of a List of all the Molecules that should be drawn.
 **/ 
 public ArrayList<IMolecule> exposeModel()
 {
   return molecules; 
 }
 
 /**
 * Assign new data to this model instance, e.g. after an event in the controller,
 * for example a bond or an atom has been added/removed/moved.
 * @param newData The new model data for this instance, e.g. the new list
 * of molecules that should be drawn.
 **/
 public void updateModel(ArrayList<IMolecule> newData)
 {
   molecules = newData; 
 }
 
  /**
 * @param pos The mouse coordinates as Pair.
 * @return Returns the Atom which is the nearest to the specified mouse
 * click coordinates.
 **/ 
 public IAtom getAtomForClick(Pair pos)
 {
	 IVector2 vecPos = new Vector2((float)pos.getX(),
									(float)pos.getY());
									
	 float minDist = 10000f;  // VERY high distance								
	 
	 IAtom nearestAtom = null;  // No nearest atom found (yet)
	 
	 /* Iterate over all molecules */								
	 for(IMolecule mol : molecules)
	 {
		 /* Then iterate over all atoms of the current molecule */
		 for(IAtom atm : mol.getAtoms())
		 {
			 if(atm.getPosition().dist(vecPos) < minDist)
			 {
				 minDist = atm.getPosition().dist(vecPos);
				 nearestAtom = atm;
			 }
		 }
	 }
	 
	 return nearestAtom;
 }
 
 
  /**
 * Adds the specified IMolecule instance to the model.
 * @param moleculeToAdd The IMolecule instance to add to this model.
 */
 public void addMolecule(IMolecule moleculeToAdd)
 {
	 molecules.add(moleculeToAdd);
	 
	 updateModel(molecules);  // Signal that model has changed here!
 }
 
 
 /**
 * Removes the specified IMolecule instance from the model.
 * @param moleculeToRemove The IMolecule instance that should be removed.
 * @return Returns the success of the removal as a boolean, e.g. it 
 * returns true if the molecule was found in and finally removed from 
 * the model, and returns false otherwise.
 */
 public boolean removeMolecule(IMolecule moleculeToRemove)
 {
	 boolean foundMolecule = false;
	 ArrayList<IMolecule> afterRemoval = new ArrayList<IMolecule>();
	 for(IMolecule mol : molecules)
	 {
		 if(mol != moleculeToRemove)
		 {
			 afterRemoval.add(mol);
		 }else
			foundMolecule = true;  // Don't add to afterRemoval, so
									// effectively remove it from
	 }								// the new model!
	 if(foundMolecule)
		this.updateModel(afterRemoval);
	 return foundMolecule;
 }
 
  /**
 * Given an IAtom atm, this method returns the molecule as IMolecule 
 * that contains this atom.
 * @param atm The IAtom that the returned molecule is a part of.
 * @return The molecule that contains the specified molecule. If no
 * molecule in the model contains the IAtom atm, null is return
 * instead. 
 */ 
 public IMolecule getMoleculeForAtom(IAtom atm)
 {
	 for(IMolecule mol : molecules)
	 {
		 if(mol.containsAtom(atm))  // found right molecule
			return mol;  // so return it.
	 }  // finished iterating over all molecules
	 return null;  // still no result, so return null.
 }
 
 
 
 
 
 
}
